package com.starsoft.smdc.dao;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.starsoft.frame.core.orm.BaseDao;
import com.starsoft.frame.core.orm.PageObject;
import com.starsoft.frame.util.DateUtil;
import com.starsoft.frame.util.StringUtil;
import com.starsoft.smdc.bean.SmdcDiv;
import com.starsoft.smdc.bean.SmdcDivId;
import com.starsoft.smdc.bean.SmdcFundamental;
import com.starsoft.smdc.bean.SmdcSecurity;

@Repository
public class DivDao extends BaseDao<SmdcDiv, SmdcDivId>{
	
	@Autowired
	FundamentalDao  fundamentalDao;
	
	public SmdcDiv get(SmdcDivId id){
		return fundamentalDao.getDiv(id);
	}
	
	public void delete(SmdcDiv div){
		fundamentalDao.deleteDiv(div);
	}
	
	public void saveOrUpdate(SmdcDiv div){
		fundamentalDao.saveDiv(div);
	}
	
	public Date getMaxDivDate(SmdcSecurity security){
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		Date maxDate = null;
		for(SmdcDiv div : fundamental.getSmdcDivs()){
			if(maxDate != null && div.getId().getDivDate()!=null && maxDate.before(div.getId().getDivDate())){
				maxDate = div.getId().getDivDate();
			} else if(maxDate == null){
				maxDate = div.getId().getDivDate();
			}
		}
		return maxDate;
	}
	
	/**
	 * 
	 * @param security
	 * @param beginDate (divDate>=beginDate)
	 * @return
	 */
	public List<SmdcDiv> getDivDateAfter(SmdcSecurity security, Date beginDate){
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		List<SmdcDiv> divs = new ArrayList<SmdcDiv>();
		Date beginDateFloor = DateUtil.floorTime(beginDate);
		for(SmdcDiv div : fundamental.getSmdcDivs()){
			if(!div.getId().getDivDate().before(beginDateFloor)){
				divs.add(div);
			}
		}
		sortDivList(divs);
		return divs;
	}

	/***
	 * 
	 * @param security
	 * @param endDate (divDate<=endDate)
	 * @return
	 */
	public SmdcDiv getDivDateBeforeOne(SmdcSecurity security, Date endDate) {
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		SmdcDiv result = null;
		for(SmdcDiv div : fundamental.getSmdcDivs()){
			Date divDatet = div.getId().getDivDate();
			if(!divDatet.after(endDate)){
				if(result != null &&  result.getId().getDivDate().before(divDatet)){
					result = div;
				} else if(result == null){
					result = div;
				}
			}
		}
		return result;
	}
	
	
	public List<SmdcDiv> getPbDateBefore(SmdcSecurity security, Date endDate) {
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		List<SmdcDiv> result = new ArrayList<SmdcDiv>();
		for(SmdcDiv div : fundamental.getSmdcDivs()){
			if(!div.getPublishDate().after(endDate)){
				result.add(div);
			}
		}
		return result;
	}
	/**
	 * beginDate<=divDate<=endDate
	 * @param security
	 * @param beginDate
	 * @param endDate
	 * @return
	 */
	public List<SmdcDiv> getDivDateBetween(SmdcSecurity security, Date beginDate, Date endDate){
		SmdcFundamental fundamental = fundamentalDao.get(security.getSecId());
		List<SmdcDiv> divs = new ArrayList<SmdcDiv>();
		Date beginDateFloor = DateUtil.floorTime(beginDate);
		for(SmdcDiv div : fundamental.getSmdcDivs()){
			Date divDate = div.getId().getDivDate();
			if(!beginDateFloor.after(divDate) && !endDate.before(divDate)){
				divs.add(div);
			}
		}
		sortDivList(divs);
		return divs;
	}
	
	public Map<String, Object> pageQuery(PageObject po, String secId, Date beginDate, Date endDate) {
		List<Criterion> criterions = new ArrayList<Criterion>();
		if(!StringUtil.isEmpty(po.getSort())){
			String sort = po.getSort().replace("secId", "id.secId").replace("divDate", "id.divDate");
			po.setSort(sort);
		}
		if(!StringUtil.isEmpty(secId)){
			criterions.add(Restrictions.like("id.secId", secId, MatchMode.ANYWHERE));
		}
		if(beginDate!=null){
			criterions.add(Restrictions.ge("id.divDate", beginDate));
		}
		if(endDate!=null){
			criterions.add(Restrictions.le("id.divDate", endDate));
		}
		return pageQuery(entityClass, po, criterions);
	}
	
	private void sortDivList(List<SmdcDiv> divList) {
		Collections.sort(divList,
			(SmdcDiv o1, SmdcDiv o2) -> {
				Date div1 = o1.getId().getDivDate();
				Date div2 = o2.getId().getDivDate();
				if(div1.before(div2)){
					return -1;
				} else if(div1.equals(div2)){
					return 0;
				} else {
					return 1;
				}
			});
	}
}
